package com.wzdigit.wms.common.utils;

import org.apache.commons.lang3.StringUtils;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 数字工具
 */
public class BigDecimalUtil {

    /**
     * 默认值0
     */
    public static final BigDecimal DEFAULT_ZERO = new BigDecimal("0");

    private static final Pattern isNumeric = Pattern.compile("[0-9]*");

    private static final Pattern isNumer = Pattern.compile("[0-9]{1,}");
    
    /**
     * 比较连个值相等
     * @param v1
     * @param v2
     * @return
     */
    public static boolean compateEquesTo(BigDecimal v1 ,BigDecimal v2) {
    	if(v1 == null) {
    		return false;
    	}
    	return v1.compareTo(v2) == 0 ?true :false;
    }
    
    /**
     * 判断v1小于v2
     * @param v1
     * @param v2
     * @return
     */
    public static boolean compateToLess(BigDecimal v1 ,BigDecimal v2) {
    	if(v1 == null) {
    		return false;
    	}
    	return v1.compareTo(v2) == -1 ?true :false;
    }
    
    /**
     * 判断v1大于v2
     * @param v1
     * @param v2
     * @return
     */
    public static boolean compateToGreat(BigDecimal v1 ,BigDecimal v2) {
    	if(v1 == null) {
    		return false;
    	}
    	return v1.compareTo(v2) == 1 ?true :false;
    }

    /**
     * 计算数字字符串有效的小数位数
     *
     * @param digit 数字字符串
     * @return 有效的小数位数
     */
    public static int getValidDecimals(String digit) {
        boolean flag = false;
        do {
            if (!digit.contains(".")) {
                return 0;
            }
            int len = digit.length() - 1;
            String lastChar = digit.charAt(len) + "";
            if ("0".equals(lastChar)) {
                digit = digit.substring(0, len);
                flag = true;
            } else {
                if (".".equals(lastChar)) {
                    digit = digit.substring(0, len);
                }
                flag = false;
            }
            // System.out.println(digit);
        } while (flag);
        BigDecimal bigD = new BigDecimal(digit);
        return bigD.scale();
    }

    /**
     * 是否正整数
     *
     * @param num 不等于空并且大于0为正整数
     * @return
     */
    public static boolean isPositLong(Long num) {
        if (num == null || num <= 0) {
            return false;
        }
        return true;
    }

    public static boolean isPositLongStr(String num) {
        if (StringUtils.isBlank(num)) {
            return false;
        }
        try {
            long num2 = Long.parseLong(num);
            if (num2 <= 0) {
                return false;
            }
        } catch (NumberFormatException e) {
            return false;
        }
        return true;
    }

    public static boolean isPositInt(Integer num) {
        if (num == null || num <= 0) {
            return false;
        }
        return true;
    }

    public static boolean isNumeric(String str) {
        return isNumeric.matcher(str).matches();
    }

    /**
     * 判断字符串是否数字字符串
     * @param str
     * @return
     */
    public static boolean isNumer(String str) {
        if (StringUtils.isBlank(str)) {
            return false;
        }
        return isNumer.matcher(str).matches();
    }

    /**
     * 数字字符串转Integer类型
     *
     * @param str 要转换的数字字符
     * @param propertyName 属性名称
     * @return
     * @throws Exception
     */
    public static Integer strToNum(String str, String propertyName) throws Exception {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        Integer num;
        try {
            num = Integer.valueOf(str);
        } catch (NumberFormatException e) {
            throw new Exception(propertyName+"格式不正确！") ;
        }
        return num;
    }

    /**
     * 数字字符串转Long类型
     *
     * @param str 要转换的数字字符
     * @param propertyName 属性名称
     * @return
     * @throws Exception
     */
    public static Long strToLong(String str, String propertyName) throws Exception {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        Long num;
        try {
            num = Long.valueOf(str);
        } catch (NumberFormatException e) {
            throw new Exception(propertyName+"格式不正确！") ;
        }
        return num;
    }

    /**
     * 数字字符串转Integer类型
     *
     * @param str 要转换的数字字符
     * @param propertyName 属性名称
     * @return
     * @throws Exception
     */
    public static Integer strToInteger(String str, String propertyName) throws Exception {
        if (StringUtils.isBlank(str)) {
            return null;
        }
        Integer num;
        try {
            num = Integer.valueOf(str);
        } catch (NumberFormatException e) {
            throw new Exception(propertyName+"格式不正确！") ;
        }
        return num;
    }

    public static boolean isDouble(String propertyValue) {
        boolean isDouble = false;
        try {
            Double.parseDouble(propertyValue);
            isDouble = true;
        } catch (NumberFormatException ex) {
            isDouble = false;
        }
        return isDouble;
    }

    /**
     * 格式化float数据保留len小数
     * @Title: formatFloat
     * @param @param num
     * @param @param len
     * @param @return
     * @return double 返回类型
     * @throws
     */
    public static float formatFloat(float num, int len) {
        String fmt = "";
        for (int i = 0; i < len; i++) {
            fmt += "0";
        }
        DecimalFormat df = new DecimalFormat("#." + fmt);
        float result = Float.parseFloat(df.format(num));
        return result;
    }


    /**
     * 请各位同学不要改我的代码 格式化double数据，保留len长度小数，自动四舍五入
     * @param num
     * @param len
     * @return
     */
    public static double formatDoubleForSolr(double num, int len) {
        String fmt = "";
        for (int i = 0; i < len; i++) {
            fmt += "0";
        }
        DecimalFormat df = new DecimalFormat("#." + fmt);
        double result = Double.parseDouble(df.format(num));
        return result;
    }

    /**
     * 多个数相加
     * @param args 变参
     * @return
     */
    public static BigDecimal add(BigDecimal... args) {
        BigDecimal total = BigDecimalUtil.DEFAULT_ZERO;
        for (int i = 0; i < args.length; i++) {
            if (args[i] == null) {
                continue;
            }
            total = total.add(args[i]);
        }
        return total;
    }

    /**
     * 多个数相加，保留指定位数精度
     * @param scale 小数点位数
     * @param roundParam 四舍五入还是直接截取 0 :四舍五入，1：直接截取
     * @param args 变参
     * @return
     */
    public static BigDecimal add(int scale, int roundParam, BigDecimal... args) {
        BigDecimal total = BigDecimalUtil.DEFAULT_ZERO;
        for (int i = 0; i < args.length; i++) {
            if (args[i] == null) {
                continue;
            }
            total = total.add(args[i]);
        }
        return total.setScale(scale, roundParam);
    }

    /**
     * 截取小数
     * @param scale
     * @param bigDecimal
     * @return
     */
    public static BigDecimal cutBigDecimal(int scale , BigDecimal bigDecimal) {
        return  bigDecimal.setScale(scale,BigDecimal.ROUND_DOWN);
    }

    /**
     * 按指定位数四舍五入
     * @param scale
     * @param bigDecimal
     * @return
     */
    public static BigDecimal roundHalfUp(int scale , BigDecimal bigDecimal) {
        return  bigDecimal.setScale(scale,BigDecimal.ROUND_HALF_UP);
    }



    /**
     * 多个数相乘，并保留多少位小数
     * @param scale 多少位小数
     * @param roundParam 四舍五入还是直接截取 0 :四舍五入，1：直接截取
     * @param args 参数列表
     * @return
     */
    public static BigDecimal multiply(int scale, int roundParam, BigDecimal... args) {
        if (null != args && args.length > 0) {
            BigDecimal total = args[0];
            if (args.length > 1) {
                for (int i = 1; i < args.length; i++) {
                    if (args[i] == null) {
                        continue;
                    }
                    total = total.multiply(args[i]);
                }
            }
            return total.setScale(scale, roundParam);
        }
        return BigDecimalUtil.DEFAULT_ZERO;
    }

    /**
     * 多个数相乘
     * @param args 参数列表
     * @return
     */
    public static BigDecimal multiply(BigDecimal... args) {
        if (null != args && args.length > 0) {
            BigDecimal total = args[0];
            if (args.length > 1) {
                for (int i = 1; i < args.length; i++) {
                    if (args[i] == null) {
                        continue;
                    }
                    total = total.multiply(args[i]);
                }
            }
            return total;
        }
        return BigDecimalUtil.DEFAULT_ZERO;
    }

    /**
     * 除以多个数，并保留固定位数小数，
     * @param scale 多少位小数
     * @param roundParam 舍五入还是直接截取 0 :四舍五入，1：直接截取
     * @param dividend 被除数
     * @param divisors 除数
     * @return
     */
    public static BigDecimal divide(int scale, int roundParam, BigDecimal dividend, BigDecimal... divisors) {
        return getDivideBigDecimal(dividend, scale, roundParam , divisors);
    }

    /**
     * 除以多个数, 默认保留2位，做四舍五入
     * @param dividend 被除数
     * @param divisors 除数
     * @return
     */
    public static BigDecimal divide(BigDecimal dividend, BigDecimal... divisors) {
        return getDivideBigDecimal(dividend, 2, BigDecimal.ROUND_HALF_UP, divisors);
    }

    private static BigDecimal getDivideBigDecimal(BigDecimal dividend, int scale, int roundingMode, BigDecimal[] divisors) {
        if(null != dividend && dividend.compareTo(DEFAULT_ZERO) != 0) {
            if (null != divisors && divisors.length > 0) {
                for (int i = 0; i < divisors.length; i++) {
                    if (divisors[i] == null) {
                        continue;
                    }
                    if(divisors[i].compareTo(DEFAULT_ZERO) == 0) {
                        return BigDecimalUtil.DEFAULT_ZERO;
                    }
                    dividend = dividend.divide(divisors[i], scale, roundingMode);
                }
            }
            return dividend;
        }
        return BigDecimalUtil.DEFAULT_ZERO;
    }


    /**
     * 连续相减 向下截取
     * @param scale 保留小数点位数
     * @param roundParam 四舍五入还是直接截取 0 :四舍五入，1：直接截取
     * @param minuend 被减数
     * @param args 多个减数
     * @return
     */
    public static BigDecimal sub(int scale, int roundParam, BigDecimal minuend, BigDecimal... args) {
        if(minuend != null) {
            for (int i = 0; i < args.length; i++) {
                if(args[i] != null) {
                    minuend = minuend.subtract(args[i]);
                }
            }
            return minuend.setScale(scale, roundParam);
        }
        return BigDecimalUtil.DEFAULT_ZERO;
    }

    /**
     * 连续相减 向下截取
     * @param minuend 被减数
     * @param args 多个减数
     * @return
     */
    public static BigDecimal sub(BigDecimal minuend, BigDecimal... args) {
        if(minuend != null) {
            for (int i = 0; i < args.length; i++) {
                if(args[i] != null) {
                    minuend = minuend.subtract(args[i]);
                }
            }
            return minuend;
        }
        return BigDecimalUtil.DEFAULT_ZERO;
    }

    /**
     * 验证是不是正整数
     * @param value 要验证的字符串
     * @return 如果是符合格式的字符串,返回 <b>true </b>,否则为 <b>false </b>
     */
    public static boolean NegatineNumber(String value) {
        String V_POSITIVE_NUMBER = "^[1-9]\\d*|0$";
        return match(V_POSITIVE_NUMBER, value);
    }

    /**
     * 验证正浮点数
     * @param value 要验证的字符串
     * @return 如果是符合格式的字符串,返回 <b>true </b>,否则为 <b>false </b>
     */
    public static boolean Posttive_float(String value) {
        String V_POSTTIVE_FLOAT = "^[0-9]\\d*.\\d*|0.\\d*[1-9]\\d*$";
        return match(V_POSTTIVE_FLOAT, value);
    }

    /**
     * @param regex 正则表达式字符串
     * @param str 要匹配的字符串
     * @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
     */
    private static boolean match(String regex, String str) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    /**
     * 取负数
     * @param num 数据
     * @return
     */
    public static BigDecimal negate(BigDecimal num) {
        return num.multiply(new BigDecimal("-1"));
    }

    /**
     * 对比是否相等，如果有一个相等就返回ture
     * @param beCompValue 被比较值
     * @param compValues 比较值
     * @return
     */
    public static boolean manyIntOrEqual(int beCompValue, int... compValues) {
        for (int i = 0; i < compValues.length; i++) {
            if(beCompValue == compValues[i]) {
                return true;
            }
        }
        return false;
    }


    public static BigDecimal strToBigDecimal(String propertyValue, String propertyName) throws Exception {
        try {
            return new BigDecimal(propertyValue);
        } catch (NumberFormatException ex) {
            throw new Exception(propertyName+"格式不正确！") ;
        }
    }

    public static BigDecimal doubleToBigDecimal(Double num) {
        if(null ==num) {
            return BigDecimalUtil.DEFAULT_ZERO;
        }
        return new BigDecimal(num + "");
    }
}
